/*
 * File:   main.c
 * Author: frank
 *
 * Created on February 15, 2015, 12:24 PM
 */

#include <peripheral/timer.h>
#include <peripheral/osc.h>
#include "TickTimer.h"

static TICKTIMER_DATA timers[TICKTIMER_MAXIDS];
TICKTIMER_CLIENT clients[TICKTIMER_MAXCLIENTS];

void TickTimer_Init(){
    // All callbacks are cleared.
    uint8_t index;
    for (index = 0; index < TICKTIMER_MAXCLIENTS; index++){
        clients[index].tickcallback = NULL;
        clients[index].tickcallbackID = 0;
    }
    // All delays are cleared.  Do not depend on these being 0 if not used.
    for (index = 0; index < TICKTIMER_MAXIDS; index++){
        timers[index].ticks = 0;
        timers[index].oneShot = false;
        timers[index].active = false;
        timers[index].currentTicks = 0;
    }

    uint32_t pclk = SYS_CLK_FREQ/1;
    uint32_t period = 5000;

    OpenTimer1(T1_ON | T1_IDLE_CON | T1_PS_1_8 | T1_SOURCE_INT,  period);
    ConfigIntTimer1(T1_INT_ON | TICKTIMER_IP | TICKTIMER_ISP);
}

// Returns true if added
bool TickTimer_SetTickCallbackID(TickTimer_TickCallback function, uint8_t id){
   uint8_t index;
    for (index = 0; index < TICKTIMER_MAXCLIENTS; index++){
        if (clients[index].tickcallback == NULL){
            clients[index].tickcallback = function;
            clients[index].tickcallbackID = id;
            return true;
        }
    }
    return false;
}
// Returns true if added
bool TickTimer_SetTickCallback(TickTimer_TickCallback function){
    TickTimer_SetTickCallbackID(function, 0);
}

// Remove client from callback
void TickTimer_RemoveTickCallback(TickTimer_TickCallback function){
    uint8_t index;
    for (index = 0; index < TICKTIMER_MAXCLIENTS; index++){
        if (clients[index].tickcallback == function){
            clients[index].tickcallback = NULL;
        }
    }
}

// Set a tick time
uint8_t TickTimer_SetTickTime(bool oneShot, unsigned int ms){
    uint8_t index;
    for (index = 0; index < TICKTIMER_MAXIDS; index++){
        if (timers[index].ticks == 0){
            timers[index].ticks = ms;
            timers[index].oneShot = oneShot;
            timers[index].active = false;
            return index + 1;
        }
    }
    return 0;
}

void TickTimer_RemoveTickTime(uint8_t id){
    if (id > 0 && id <= TICKTIMER_MAXIDS){
        id--;
        timers[id].ticks = 0;
        timers[id].oneShot = false;
        timers[id].active = false;
    }
}

// Start the tick timer
bool TickTimer_Start(uint8_t id){
    if (id > 0 && id <= TICKTIMER_MAXIDS){
        id--;
        timers[id].active = true;
        timers[id].currentTicks = 0;
    }
}

void TickTimer_Stop(uint8_t id){
    if (id > 0 && id <= TICKTIMER_MAXIDS){
        id--;
        timers[id].active = false;
        timers[id].currentTicks = 0;
    }
}

void __ISR( _TIMER_1_VECTOR, TICKTIMER_INT) Timer1Interrupt( void){
    DisableIntT1;
    uint8_t index;
    for (index = 0; index < TICKTIMER_MAXIDS; index++){
        if (timers[index].active == true){
            timers[index].currentTicks++;
            if (timers[index].currentTicks >= timers[index].ticks){
                uint8_t cbIndex;
                for (cbIndex = 0; cbIndex < TICKTIMER_MAXCLIENTS; cbIndex++){
                    if (clients[index].tickcallback != NULL){
                        if (clients[index].tickcallbackID == 0 || clients[index].tickcallbackID == cbIndex + 1){
                            clients[index].tickcallback(clients[index].tickcallbackID);
                        }
                    }
                }
                timers[index].currentTicks = 0;
                if (timers[index].oneShot == true){
                    timers[index].active = false;
                }
            }
        }
    }
    mT1ClearIntFlag();
    EnableIntT1;
}